/*
 * SocketMonitor.cpp
 *
 *  Created on: 2012-12-27
 *      Author: yangentao@gmail.com
 */

#include <boost/function.hpp>
#include <boost/bind.hpp>
#include "SocketMonitor.h"

#include "../StreamLog.h"
namespace yet {

SocketMonitor::SocketMonitor() {
	isCancel = false;
}

SocketMonitor::~SocketMonitor() {
	if(!isCancel){
		isCancel = true;
		sock.close();
	}
	thread.waitFinish();
}
int SocketMonitor::onRun(void* arg) {
	while (!isCancel) {
		FdSet fs;
		fs.set(sock.sock);
		int n = sock.select(&fs, 0, 0, 1);
		if (isCancel) {
			return 0;
		}
		if (n > 0) {
			if (fs.isSet(sock.sock)) {
				char buf[8];
				int m = sock.recv(buf, 8, MSG_PEEK);
				if (m == 0) {
					isCancel = true;
					if (OnClose) {
						SocketError e(0);
						OnClose(sock.sock, e);
					}
					return 0;
				} else if (m > 0) {
					continue;
				} else {
					isCancel = true;
					sock.close();
					if (OnClose) {
						SocketError e;
						OnClose(sock.sock, e);
					}
					return 0;
				}
			}
			continue;
		}
		if (n == 0) { //timeout
			continue;
		}
		if (n < 0) {
			SocketError e;
			slog << err << "Socket Monitor Error: " << e.getCode() << " " << e.getCodeName() << end;
			return 0;
		}
	}
	return 0;
}
void SocketMonitor::monitor(SOCKET s, boost::function<void (SOCKET s, SocketError e)> closeCallback) {
	isCancel = false;
	sock.sock = s;
	OnClose = closeCallback;
	thread.OnRun = boost::bind(&SocketMonitor::onRun, this, _1);
	thread.setPriority(Thread::priorityHight);
	thread.start();
	SwitchToThread();
}
void SocketMonitor::cancel(){
	isCancel = true;
}
} /* namespace yet */
